#include <cassert>
#include "SDL.h"
#include <iostream>

const int TAILLE_SPRITE=32;
// va permettre de simplifier l'incrémentation du nombre de bebetes en début de niveau
int compteur_ajout_bebetes;

SDL_Surface *SDL_load_image(const char* filename);
void SDL_apply_surface( SDL_Surface* source, SDL_Surface* destination, int x, int y );


/* Cette procédure ne sera appellée qu'une seule fois au moment du lancement du
 * jeu (même si on décide de recommencer une partie, cette fonction ne sera pas
 * relancée puisqu'elle effectue toutes les initialisation dont certaines ne
 * sont pas à refaire tant qu'on a pas fermer la fenetre de jeu).
 * Elle prend en paramètre l'adresse d'une structure SDL. */
void sdljeuInit(Ssdljeu& sj)
{
	init_jeu (&sj.jeu);
	// déclaration des variables :
	char caracteristique_tour1_portee[25] = "";
	char caracteristique_tour1_vitesse[25] = "";
	char caracteristique_tour1_puissance[25] = "";
	char caracteristique_tour1_prix[25] = "";
	char caracteristique_tour2_portee[25] = "";
	char caracteristique_tour2_vitesse[25] = "";
	char caracteristique_tour2_puissance[25] = "";
	char caracteristique_tour2_prix[25] = "";
	char caracteristique_tour3_portee[25] = "";
	char caracteristique_tour3_vitesse[25] = "";
	char caracteristique_tour3_puissance[25] = "";
	char caracteristique_tour3_prix[25] = "";
	char caracteristique_tour4_portee[25] = "";
	char caracteristique_tour4_vitesse[25] = "";
	char caracteristique_tour4_puissance[25] = "";
	char caracteristique_tour4_prix[25] = "";
	int portee1, vitesse1, puissance1, prix1;
	int portee2, vitesse2, puissance2, prix2;
	int portee3, vitesse3, puissance3, prix3;
	int portee4, vitesse4, puissance4, prix4;
	Stype* adresse_types;
	Stypetour* ad_typ1;
	Stypetour* ad_typ2;
	Stypetour* ad_typ3;
	Stypetour* ad_typ4;
	
	assert (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER)!=-1);

	// déclarations liées à l'écran de jeu :
	int dimx, dimy;
	dimx = (get_longueur (sj.jeu.terrain) + 9)*TAILLE_SPRITE;
	dimy = (get_hauteur (sj.jeu.terrain))*TAILLE_SPRITE;
	sj.ecran = SDL_SetVideoMode (dimx, dimy, 32, SDL_SWSURFACE);
	assert (sj.ecran);
	SDL_WM_SetCaption ("A mort les Bebetes !!", NULL);

	// chargement des images :
	sj.chemin = SDL_load_image("chemin.bmp");
	assert (sj.chemin);
	sj.libre = SDL_load_image("Libre2.bmp");
	assert (sj.libre);
	sj.tour1= SDL_load_image ("Tour1.bmp");
	assert (sj.tour1);
	sj.tour2= SDL_load_image ("Tour2.bmp");
	assert (sj.tour2);
	sj.tour3= SDL_load_image ("Tour3.bmp");
	assert (sj.tour3);
	sj.tour4= SDL_load_image ("Tour4.bmp");
	assert (sj.tour4);
	sj.bebete= SDL_load_image ("bebete.bmp");
	assert (sj.bebete);
	// permet d'enlever le fond blanc derrière la bebete
	SDL_SetColorKey(sj.bebete, SDL_SRCCOLORKEY, SDL_MapRGB (sj.bebete->format,255,255,255));
	
	// initialisation du menu : (on va ici créer une surface par information)
	// généralités
	TTF_Init();
	TTF_Font *police1 = NULL;
	TTF_Font *police4 = NULL;
	police1 = TTF_OpenFont("/usr/share/fonts/truetype/thai/Garuda-Bold.ttf", 20);
	police4 = TTF_OpenFont("/usr/share/fonts/truetype/thai/Garuda-Bold.ttf", 10);
	SDL_Color couleurNoire = {0, 0, 0}, couleurBlanche = {255, 255, 255}, couleurGrise = {100,100,100}, couleurBleue = {0,0,255}, couleurVerte = {0, 255, 0}, couleurJaune = {255, 255, 0}, couleurOrange = {255, 99, 9}, couleurRouge = {255,0,0};;
	// titre
	sj.titre = TTF_RenderText_Shaded(police1, "MENU", couleurBlanche, couleurNoire);
	// boutton start
	sj.boutton_start = TTF_RenderText_Shaded(police1, " Start ", couleurNoire, couleurGrise);
	// caractéristiques des tours : (il ne faut ici pas oublier qu'on doit écrire le nom de la caractéristique pui sa valeur) 
	//tour1
	adresse_types = sj.jeu.types;
	ad_typ1 = get_listetype(adresse_types,10);
	portee1 = get_portee(ad_typ1);
	sprintf(caracteristique_tour1_portee, "Portee : %d", portee1);
	sj.portee1 = TTF_RenderText_Shaded(police4, caracteristique_tour1_portee, couleurBleue, couleurNoire);
	vitesse1 = get_vitesse(ad_typ1);
	sprintf(caracteristique_tour1_vitesse, "Vitesse : %d", vitesse1);
	sj.vitesse1 = TTF_RenderText_Shaded(police4, caracteristique_tour1_vitesse, couleurBleue, couleurNoire);
	puissance1 = get_portee(ad_typ1);
	sprintf(caracteristique_tour1_puissance, "Puissance : %d", puissance1);
	sj.puissance1 = TTF_RenderText_Shaded(police4, caracteristique_tour1_puissance, couleurBleue, couleurNoire);
	prix1 = get_portee(ad_typ1);
	sprintf(caracteristique_tour1_prix, "PRIX : %d", prix1);
	sj.prix1 = TTF_RenderText_Shaded(police4, caracteristique_tour1_prix, couleurRouge, couleurNoire);
	//tour2
	ad_typ2 = get_listetype(adresse_types,20);
	portee2 = get_portee(ad_typ2);
	sprintf(caracteristique_tour2_portee, "Portee : %d", portee2);
	sj.portee2 = TTF_RenderText_Shaded(police4, caracteristique_tour2_portee, couleurVerte, couleurNoire);
	vitesse2 = get_vitesse(ad_typ2);
	sprintf(caracteristique_tour2_vitesse, "Vitesse : %d", vitesse2);
	sj.vitesse2 = TTF_RenderText_Shaded(police4, caracteristique_tour2_vitesse, couleurVerte, couleurNoire);
	puissance2 = get_portee(ad_typ2);
	sprintf(caracteristique_tour2_puissance, "Puissance : %d", puissance2);
	sj.puissance2 = TTF_RenderText_Shaded(police4, caracteristique_tour2_puissance, couleurVerte, couleurNoire);
	prix2 = get_portee(ad_typ2);
	sprintf(caracteristique_tour2_prix, "PRIX : %d", prix2);
	sj.prix2 = TTF_RenderText_Shaded(police4, caracteristique_tour2_prix, couleurRouge, couleurNoire);
	//tour3
	ad_typ3 = get_listetype(adresse_types,30);
	portee3 = get_portee(ad_typ3);
	sprintf(caracteristique_tour3_portee, "Portee : %d", portee3);
	sj.portee3 = TTF_RenderText_Shaded(police4, caracteristique_tour3_portee, couleurJaune, couleurNoire);
	vitesse3 = get_vitesse(ad_typ3);
	sprintf(caracteristique_tour3_vitesse, "Vitesse : %d", vitesse3);
	sj.vitesse3 = TTF_RenderText_Shaded(police4, caracteristique_tour3_vitesse, couleurJaune, couleurNoire);
	puissance3 = get_portee(ad_typ3);
	sprintf(caracteristique_tour3_puissance, "Puissance : %d", puissance3);
	sj.puissance3 = TTF_RenderText_Shaded(police4, caracteristique_tour3_puissance, couleurJaune, couleurNoire);
	prix3 = get_portee(ad_typ3);
	sprintf(caracteristique_tour3_prix, "PRIX : %d", prix3);
	sj.prix3 = TTF_RenderText_Shaded(police4, caracteristique_tour3_prix, couleurRouge, couleurNoire);
	//tour4
	ad_typ4 = get_listetype(adresse_types,40);
	portee4 = get_portee(ad_typ4);
	sprintf(caracteristique_tour4_portee, "Portee : %d", portee4);
	sj.portee4 = TTF_RenderText_Shaded(police4, caracteristique_tour4_portee, couleurOrange, couleurNoire);
	vitesse4 = get_vitesse(ad_typ4);
	sprintf(caracteristique_tour4_vitesse, "Vitesse : %d", vitesse4);
	sj.vitesse4 = TTF_RenderText_Shaded(police4, caracteristique_tour4_vitesse, couleurOrange, couleurNoire);
	puissance4 = get_portee(ad_typ4);
	sprintf(caracteristique_tour4_puissance, "Puissance : %d", puissance4);
	sj.puissance4 = TTF_RenderText_Shaded(police4, caracteristique_tour4_puissance, couleurOrange, couleurNoire);
	prix4 = get_portee(ad_typ4);
	sprintf(caracteristique_tour4_prix, "PRIX : %d", prix4);
	sj.prix4 = TTF_RenderText_Shaded(police4, caracteristique_tour4_prix, couleurRouge, couleurNoire);
	
	TTF_CloseFont(police1);
	TTF_CloseFont(police4);
}

/* Cette procédure permet d'afficher le terrain dans la fenetre de jeu à
 * partir du terrain (eventuellement mis à jour).
 * Elle prend en paramètre l'adresse d'une structure SDL. */
void SDL_aff_terrain(Ssdljeu& sj)
{
	// Afin de protéger de toute modification non souhaitée le terrain,
	// on commence par faire une copie qui ne pourra être modifiée !
	const Sterrain& ter = (*sj.jeu.terrain);
	int x; // va servir d'indice de colonne
	int y; // va servir d'indice de ligne
	// on va maintenant remplir colonne par colonne :
	for (x=0;x<get_longueur(&ter);++x)
	{
		for (y=0;y<get_hauteur(&ter);++y)
		{
			int valter;
			valter=get_terrain (x,y,&ter);
			// selon la valeur rencontrée, on charge l'image correspondante
			if (valter==1)
			{
				SDL_apply_surface(sj.chemin, sj.ecran, x*TAILLE_SPRITE, y*TAILLE_SPRITE);
			}
			else if (valter==0)
			{
				SDL_apply_surface(sj.libre, sj.ecran, x*TAILLE_SPRITE, y*TAILLE_SPRITE);
			}
			else if (valter==2)
			{
				SDL_apply_surface(sj.tour1, sj.ecran, x*TAILLE_SPRITE, y*TAILLE_SPRITE);
			}
			else if (valter==3)
			{
				SDL_apply_surface(sj.tour2, sj.ecran, x*TAILLE_SPRITE, y*TAILLE_SPRITE);
			}
			else if (valter==4)
			{
				SDL_apply_surface(sj.tour3, sj.ecran, x*TAILLE_SPRITE, y*TAILLE_SPRITE);
			}
			else if (valter==5)
			{
				SDL_apply_surface(sj.tour4, sj.ecran, x*TAILLE_SPRITE, y*TAILLE_SPRITE);
			}
		}
	}
}

/* Procédure qui va permettre de gérer tout ce qui concerne l'affichage
 * (excepté le terrain qui est géré dans SDL_aff_terrain). Elle prend en
 * paramètre l'adresse d'une structure SDL. */
void sdljeuAff(Ssdljeu& sj)
{
	// Polices pour affichage menu :
	TTF_Font *police2 = NULL;
	TTF_Font *police3 = NULL;
	police2 = TTF_OpenFont("/usr/share/fonts/truetype/thai/Garuda-Bold.ttf", 12);
	police3 = TTF_OpenFont("/usr/share/fonts/truetype/thai/Garuda-Bold.ttf", 15);
	SDL_Color couleurNoire = {0, 0, 0}, couleurBlanche = {255, 255, 255};
	
	
	//Remplir l'écran de blanc
	SDL_FillRect (sj.ecran, &sj.ecran->clip_rect, SDL_MapRGB (sj.ecran->format, 0, 0, 0));

	// On affiche le terrain
	SDL_aff_terrain(sj);
	
	// On affiche les bebetes qui sont sur le terrain :
	int i=0; // compteur de bebetes
	Slistebebete* lbeb;
	lbeb = sj.jeu.bebetes;
	// comme on a un nombre de bebetes au maximum égal au niveau, on affiche
	// tant qu'on a pas soit atteint cette valeur, soit plus de bebetes a afficher
	while(((get_niveau(sj.jeu.partie))>i)&&(lbeb!=NULL))
	{
		// Copier le sprite d'une bebete sur sj.ecran
		SDL_apply_surface(sj.bebete, sj.ecran, get_Xbebete((*lbeb).pbebete)*TAILLE_SPRITE, get_Ybebete((*lbeb).pbebete)*TAILLE_SPRITE);
		// incrémenter le compteur
		i++;
		// et "incrémenter" la bebete
		lbeb=(*lbeb).pbebetesuiv;
	}

// déclaration et valeurs des positions des éléments du menu :
		char vies[25] = "";
		char score[25]= "";
		char argent[25]="";
		char niveau[25] = "";
		int nbvies;
		int points_acquis;
		int argent_restant;
		int niveau_courant;
		SDL_Rect positiontitre;
		positiontitre.x = ((get_longueur(sj.jeu.terrain))+9/2-0.5)*TAILLE_SPRITE;
		positiontitre.y = 0;
		SDL_Rect positionvies;
		positionvies.x = ((get_longueur(sj.jeu.terrain))+0.5)*TAILLE_SPRITE;
		positionvies.y = TAILLE_SPRITE;
		SDL_Rect positionscore;
		positionscore.x = ((get_longueur(sj.jeu.terrain))+5)*TAILLE_SPRITE;
		positionscore.y = TAILLE_SPRITE;
		SDL_Rect positionargent;
		positionargent.x = ((get_longueur(sj.jeu.terrain))+9/4)*TAILLE_SPRITE;
		positionargent.y = 2*TAILLE_SPRITE;
		SDL_Rect positionniveau;
		positionniveau.x = ((get_longueur(sj.jeu.terrain))+9/4)*TAILLE_SPRITE;
		positionniveau.y = ((get_hauteur(sj.jeu.terrain))-1)*TAILLE_SPRITE;
		SDL_Rect positionstart;
		positionstart.x = ((get_longueur(sj.jeu.terrain))+7)*TAILLE_SPRITE;
		positionstart.y = ((get_hauteur(sj.jeu.terrain))-1)*TAILLE_SPRITE;
		//tours
		SDL_Rect positionportee1;
		positionportee1.x = ((get_longueur(sj.jeu.terrain))+1)*TAILLE_SPRITE;
		positionportee1.y = 4*TAILLE_SPRITE;
		SDL_Rect positionvitesse1;
		positionvitesse1.x = ((get_longueur(sj.jeu.terrain))+1)*TAILLE_SPRITE;
		positionvitesse1.y = 4.5*TAILLE_SPRITE;
		SDL_Rect positionpuissance1;
		positionpuissance1.x = ((get_longueur(sj.jeu.terrain))+1)*TAILLE_SPRITE;
		positionpuissance1.y = 5*TAILLE_SPRITE;
		SDL_Rect positionprix1;
		positionprix1.x = ((get_longueur(sj.jeu.terrain))+1)*TAILLE_SPRITE;
		positionprix1.y = 5.5*TAILLE_SPRITE;
		SDL_Rect positionportee2;
		positionportee2.x = ((get_longueur(sj.jeu.terrain))+5)*TAILLE_SPRITE;
		positionportee2.y = 4*TAILLE_SPRITE;
		SDL_Rect positionvitesse2;
		positionvitesse2.x = ((get_longueur(sj.jeu.terrain))+5)*TAILLE_SPRITE;
		positionvitesse2.y = 4.5*TAILLE_SPRITE;
		SDL_Rect positionpuissance2;
		positionpuissance2.x = ((get_longueur(sj.jeu.terrain))+5)*TAILLE_SPRITE;
		positionpuissance2.y = 5*TAILLE_SPRITE;
		SDL_Rect positionprix2;
		positionprix2.x = ((get_longueur(sj.jeu.terrain))+5)*TAILLE_SPRITE;
		positionprix2.y = 5.5*TAILLE_SPRITE;
		SDL_Rect positionportee3;
		positionportee3.x = ((get_longueur(sj.jeu.terrain))+1)*TAILLE_SPRITE;
		positionportee3.y = 7*TAILLE_SPRITE;
		SDL_Rect positionvitesse3;
		positionvitesse3.x = ((get_longueur(sj.jeu.terrain))+1)*TAILLE_SPRITE;
		positionvitesse3.y = 7.5*TAILLE_SPRITE;
		SDL_Rect positionpuissance3;
		positionpuissance3.x = ((get_longueur(sj.jeu.terrain))+1)*TAILLE_SPRITE;
		positionpuissance3.y = 8*TAILLE_SPRITE;
		SDL_Rect positionprix3;
		positionprix3.x = ((get_longueur(sj.jeu.terrain))+1)*TAILLE_SPRITE;
		positionprix3.y = 8.5*TAILLE_SPRITE;
		SDL_Rect positionportee4;
		positionportee4.x = ((get_longueur(sj.jeu.terrain))+5)*TAILLE_SPRITE;
		positionportee4.y = 7*TAILLE_SPRITE;
		SDL_Rect positionvitesse4;
		positionvitesse4.x = ((get_longueur(sj.jeu.terrain))+5)*TAILLE_SPRITE;
		positionvitesse4.y = 7.5*TAILLE_SPRITE;
		SDL_Rect positionpuissance4;
		positionpuissance4.x = ((get_longueur(sj.jeu.terrain))+5)*TAILLE_SPRITE;
		positionpuissance4.y = 8*TAILLE_SPRITE;
		SDL_Rect positionprix4;
		positionprix4.x = ((get_longueur(sj.jeu.terrain))+5)*TAILLE_SPRITE;
		positionprix4.y = 8.5*TAILLE_SPRITE;
		// Menu_final :
		SDL_Surface* perdu;
		TTF_Font *police1 = NULL;
		police1 = TTF_OpenFont("/usr/share/fonts/truetype/thai/Garuda-Bold.ttf", 50);
		SDL_Rect positionperdu;
	// Généralistés toujours présentes :
	// nb de vies
		nbvies = get_nbvie(sj.jeu.partie);
		sprintf(vies, "Vies restantes : %d", nbvies);
		sj.nbvie = TTF_RenderText_Shaded(police2, vies, couleurBlanche, couleurNoire);
		// score
		points_acquis = get_score(sj.jeu.partie);
		sprintf(score, "Score : %d", points_acquis);
		sj.score = TTF_RenderText_Shaded(police2, score, couleurBlanche, couleurNoire);
		// porte monaie
		argent_restant = get_argent(sj.jeu.partie);
		sprintf(argent, "Votre argent : %d", argent_restant);
		sj.argent = TTF_RenderText_Shaded(police3, argent, couleurBlanche, couleurNoire);
		// niveau
		niveau_courant = get_niveau(sj.jeu.partie);
		sprintf(niveau, "NIVEAU %d", niveau_courant);
		sj.niveau = TTF_RenderText_Shaded(police3, niveau, couleurBlanche, couleurNoire);
		
		// Collage des surfaces du menu générique sur l'écran
		SDL_BlitSurface(sj.titre, NULL, sj.ecran, &positiontitre); 
		SDL_BlitSurface(sj.nbvie, NULL, sj.ecran, &positionvies);
		SDL_BlitSurface(sj.score, NULL, sj.ecran, &positionscore);
		SDL_BlitSurface(sj.argent, NULL, sj.ecran, &positionargent);
		SDL_BlitSurface(sj.niveau, NULL, sj.ecran, &positionniveau);
		SDL_BlitSurface(sj.boutton_start, NULL, sj.ecran, &positionstart);
	// si on veut le menu basique, il reste à blitter les différents éléments
	// déclarés ci dessus et à appliquer les surfaces des 4 tours :	
	if (((*sj.jeu.menu).etat_menu)==0)
	{	
		SDL_BlitSurface(sj.portee1, NULL, sj.ecran, &positionportee1);
		SDL_BlitSurface(sj.vitesse1, NULL, sj.ecran, &positionvitesse1);
		SDL_BlitSurface(sj.puissance1, NULL, sj.ecran, &positionpuissance1);
		SDL_BlitSurface(sj.prix1, NULL, sj.ecran, &positionprix1);
		SDL_BlitSurface(sj.portee2, NULL, sj.ecran, &positionportee2);
		SDL_BlitSurface(sj.vitesse2, NULL, sj.ecran, &positionvitesse2);
		SDL_BlitSurface(sj.puissance2, NULL, sj.ecran, &positionpuissance2);
		SDL_BlitSurface(sj.prix2, NULL, sj.ecran, &positionprix2);
		SDL_BlitSurface(sj.portee3, NULL, sj.ecran, &positionportee3);
		SDL_BlitSurface(sj.vitesse3, NULL, sj.ecran, &positionvitesse3);
		SDL_BlitSurface(sj.puissance3, NULL, sj.ecran, &positionpuissance3);
		SDL_BlitSurface(sj.prix3, NULL, sj.ecran, &positionprix3);
		SDL_BlitSurface(sj.portee4, NULL, sj.ecran, &positionportee4);
		SDL_BlitSurface(sj.vitesse4, NULL, sj.ecran, &positionvitesse4);
		SDL_BlitSurface(sj.puissance4, NULL, sj.ecran, &positionpuissance4);
		SDL_BlitSurface(sj.prix4, NULL, sj.ecran, &positionprix4);
		
		// Copier le sprite de chacune des tours du menu sur sj.ecran
		SDL_apply_surface(sj.tour1, sj.ecran, (get_longueur(sj.jeu.terrain)+1)*TAILLE_SPRITE, 3*TAILLE_SPRITE);
		SDL_apply_surface(sj.tour2, sj.ecran, (get_longueur(sj.jeu.terrain)+5)*TAILLE_SPRITE, 3*TAILLE_SPRITE);
		SDL_apply_surface(sj.tour3, sj.ecran, (get_longueur(sj.jeu.terrain)+1)*TAILLE_SPRITE, 6*TAILLE_SPRITE);
		SDL_apply_surface(sj.tour4, sj.ecran, (get_longueur(sj.jeu.terrain)+5)*TAILLE_SPRITE, 6*TAILLE_SPRITE);
	}
	// sinon, si on est dans le cas de la suppression d'une tour :
	else if (((*sj.jeu.menu).etat_menu)==1)
		{
			//suppression
		}
		// sinon si on est dans le cas d'une fin de partie, 
		else if (((*sj.jeu.menu).etat_menu)==2)
		{
			perdu = TTF_RenderText_Shaded(police1, "Rejouer", couleurBlanche, couleurNoire);
			positionperdu.x = (((get_longueur(sj.jeu.terrain))+10)/3)*TAILLE_SPRITE;
			positionperdu.y = 5*TAILLE_SPRITE;
			SDL_BlitSurface(perdu, NULL, sj.ecran, &positionperdu);
		}
	
	SDL_FreeSurface(sj.nbvie);
	SDL_FreeSurface(sj.score);
	SDL_FreeSurface(sj.argent);
	SDL_FreeSurface(sj.niveau);
	TTF_CloseFont(police1);
	TTF_CloseFont(police2);
	TTF_CloseFont(police3);
}
	

/* Fonction de callback (sera appelée toutes les 120ms). Elle permettra
 * de faire avancer les bebetes et de déclancher les tirs des tours. */
Uint32 iteration_de_jeu(Uint32 intervalle, void *sj)
{
    Ssdljeu* SJ = (Ssdljeu *) sj; /* Conversion de void* en SDL_Rect* */
    // on déplace les bebetes et on tir si nécéssaire :
	deplacer((*SJ).jeu.bebetes, ((*SJ).jeu.terrain));
	tir_tour(&(*SJ).jeu);
	// si une bebete se retrouve sur le chateau, on décrémente une vie
	if (get_listebebete((*SJ).jeu.bebetes, 9, 9)!=NULL)
	{
		set_nbvie((*SJ).jeu.partie);
	}
	// si c'est la fin du niveau, on incrémente le niveau, on réinitialise
	// la liste de bebetes et on arrete cette fonction de callback
	if (fin_niveau(&(*SJ).jeu)==1)
	{
		set_niveau((*SJ).jeu.partie);
		(*SJ).jeu.bebetes = new Slistebebete;
		init_listebebete((*SJ).jeu.bebetes);
		return 0;
	}
	// si c'est la fin de la partie, on arrete également cette fonction de callback
	if ((*(*SJ).jeu.menu).etat_menu==2)
	{
		return 0;
	}
	// dans tout les autres cas, on renvoie l'intervalle afin que la fonction
	// soit rappellée automatiquement.
	return intervalle;
}


/* Fonction de callback (sera appelée toutes les 120ms). Elle permettra
 * d'insérer une bebete lorsque c'est nécéssaire (cela dépend du niveau où on est). */
Uint32 ajouterBebete(Uint32 intervalle, void *sj)
{
    Ssdljeu* SJ = (Ssdljeu *) sj; /* Conversion de void* en SDL_Rect* */
	// si on a déjà ajouté assez de bebetes, on arrete la fonction de calback
	if (((*(*SJ).jeu.partie).niveau)==compteur_ajout_bebetes)
	{
		return 0;
	}
	// sinon on ajoute une bebete, on incrémente le compteur et on renvoi
	// l'intervalle afin que la fonction soit rappellée automatiquement.
	else
	{
		ajoutbebete((*SJ).jeu.bebetes);
		// on incrémente le compteur d'ajout de bebetes afin de savoir quand il faut s'arreter d'incrémenter la liste de bebetes
		compteur_ajout_bebetes++;
		return intervalle;
	}
}

/* Cette procédure est le coeur du programme. C'est elle qui va gérer la boucle
 * d'évènement et qui va appeller lorsque nécéssaire les procédures vues ci-dessus.
 * Elle prend en paramètre l'adresse d'une structure SDL. */
void sdljeuBoucle(Ssdljeu& sj)
{
	// déclaration des variables liées aux évènements : (il ne faut pas oublier
	// que l'on doit déclarer les surfaces permettant de voir les tours qu'on
	// s'apprete à planter)
	SDL_Event event;
	SDL_Surface* nvelle_tour1;
	SDL_Surface* nvelle_tour2;
	SDL_Surface* nvelle_tour3;
	SDL_Surface* nvelle_tour4;
	SDL_Rect positiontour1;
	positiontour1.x=((get_longueur(sj.jeu.terrain))+1)*TAILLE_SPRITE;
	positiontour1.y=3*TAILLE_SPRITE;
	SDL_Rect positiontour2;
	positiontour2.x=((get_longueur(sj.jeu.terrain))+5)*TAILLE_SPRITE;
	positiontour2.y=3*TAILLE_SPRITE;
	SDL_Rect positiontour3;
	positiontour3.x=((get_longueur(sj.jeu.terrain))+1)*TAILLE_SPRITE;
	positiontour3.y=6*TAILLE_SPRITE;
	SDL_Rect positiontour4;
	positiontour4.x=((get_longueur(sj.jeu.terrain))+5)*TAILLE_SPRITE;
	positiontour4.y=6*TAILLE_SPRITE;
	bool quit = false;
	int ajout=0; // va permettre de savoir si on a une tour au bout de notre
	// souris (prete à etre plantée !)
	// chargement des images du menu :
	nvelle_tour1 = SDL_LoadBMP("Tour1.bmp");
	nvelle_tour2 = SDL_LoadBMP("Tour2.bmp");
	nvelle_tour3 = SDL_LoadBMP("Tour3.bmp");
	nvelle_tour4 = SDL_LoadBMP("Tour4.bmp");
	assert (nvelle_tour1);
	assert (nvelle_tour2);
	assert (nvelle_tour3);
	assert (nvelle_tour4);
	int longueur = get_longueur(sj.jeu.terrain);
	int hauteur = get_hauteur(sj.jeu.terrain);

	// affichage du jeu
	sdljeuAff (sj);
	
	assert (SDL_Flip(sj.ecran)!=-1);
// BOUCLE D'EVENEMENT :
	// tant que ce n'est pas la fin ...
	while (quit==false)
	{
		// tant qu'il y a des evenements à traiter : cette boucle n'est pas bloquante
		while (SDL_PollEvent(&event))
		{
			// Si l'utilisateur a cliqué sur la croix de fermeture
			if (event.type == SDL_QUIT) quit = true;
			
			// Si une action souris est effectuée
			switch (event.type)
			{
				// si on clique :
				case SDL_MOUSEBUTTONUP:
				if (((*sj.jeu.menu).etat_menu)==0)
				{
					// si on clique sur le bouton "Start", déclanchement des fonctions de callback :
					if ((event.button.x>=(longueur+7)*TAILLE_SPRITE)&&(event.button.x<=(longueur+9)*TAILLE_SPRITE)&&(event.button.y<=hauteur*TAILLE_SPRITE)&&(event.button.y>=(hauteur-1)*TAILLE_SPRITE))
					{
						// permet d'éviter que si les bebetes sont tuées dès leur arrivée sur le terrain, on continue d'en rajouter
						compteur_ajout_bebetes=1;
						sj.timer1 = SDL_AddTimer(1200, iteration_de_jeu, &sj);
						SDL_Delay(10);
						sj.timer2 = SDL_AddTimer(1200, ajouterBebete, &sj);
					}
					// si on a une tour au bout de la souris,
					if (ajout==1)
					{
						// et qu'on clique sur le terrain de jeu,
						if ((event.button.x>=0)&&(event.button.x<=(longueur*TAILLE_SPRITE))&&(event.button.y>=0)&&(event.button.y<=(hauteur*TAILLE_SPRITE)))
						{
							// a un endroit libre :
							if (get_terrain(event.button.x/TAILLE_SPRITE, event.button.y/TAILLE_SPRITE,sj.jeu.terrain)==0)
							{
								// on déclanche les modification de structure à faire
								actionsouris(&sj.jeu,'1', int(event.button.x/TAILLE_SPRITE),  int(event.button.y/TAILLE_SPRITE));
								// on libère la souris
								ajout=0;
								// et pour ne pas avoir de décalage d'affichage, on place la tour qui était au bout de la souris à l'endroit voulu : 
								positiontour1.x=(longueur+1)*TAILLE_SPRITE;
								positiontour1.y=3*TAILLE_SPRITE;
							}
							// sinon, si l'endroit n'est pas libre, on supperpose la tour sur l'emplacement d'achat (et on libere la souris)
							else
							{
								ajout=0;
								positiontour1.x=(longueur+1)*TAILLE_SPRITE;
								positiontour1.y=3*TAILLE_SPRITE;
							}
						}
						// sinon si on a cliqué hors du terrain de jeu, on supperpose la tour sur l'emplacement d'achat (et on libere la souris)
						else
						{
							ajout=0;
							positiontour1.x=(longueur+1)*TAILLE_SPRITE;
							positiontour1.y=3*TAILLE_SPRITE;
						}
					}
					// si on n'a pas de tour au bout de la souris et qu'on clique sur l'emplacement d'achat de la tour1, alors on accroche cette image au bout de la souris
					else if ((ajout==0)&&(event.button.x>=(longueur+1)*TAILLE_SPRITE)&&(event.button.x<=(longueur+2)*TAILLE_SPRITE)&&(event.button.y<=4*TAILLE_SPRITE)&&(event.button.y>=3*TAILLE_SPRITE))
					{
						ajout=1;
					}
					// on suit exactement la meme logique pour chacune des 4 tours :
					if (ajout==2)
					{
						// tour2 en bout de souris et clic sur le terrain
						if ((event.button.x>=0)&&(event.button.x<=(longueur*TAILLE_SPRITE))&&(event.button.y>=0)&&(event.button.y<=hauteur*TAILLE_SPRITE))
						{
							// emplacement de terrain libre
							if (get_terrain(event.button.x/TAILLE_SPRITE, event.button.y/TAILLE_SPRITE,sj.jeu.terrain)==0)
							{
								actionsouris(&sj.jeu,'2', int(event.button.x/TAILLE_SPRITE),  int(event.button.y/TAILLE_SPRITE));
								ajout=0;
								positiontour2.x=(longueur+5)*TAILLE_SPRITE;
								positiontour2.y=3*TAILLE_SPRITE;
							}
							// emplacement de terrain non libre
							else
							{
								ajout=0;
								positiontour2.x=(longueur+5)*TAILLE_SPRITE;
								positiontour2.y=3*TAILLE_SPRITE;
							}
						}
						// clic hors du terrain
						else
						{
							ajout=0;
							positiontour2.x=(longueur+5)*TAILLE_SPRITE;
							positiontour2.y=3*TAILLE_SPRITE;
						}
					}
					// pas de tour en bout de souris et clic sur achat tour2
					else if ((ajout==0)&&(event.button.x>=(longueur+5)*TAILLE_SPRITE)&&(event.button.x<=(longueur+6)*TAILLE_SPRITE)&&(event.button.y<=4*TAILLE_SPRITE)&&(event.button.y>=3*TAILLE_SPRITE))
					{
						ajout=2;
					}
					if (ajout==3)
					{
						// tour3 en bout de souris et clic sur le terrain
						if ((event.button.x>=0)&&(event.button.x<=longueur*TAILLE_SPRITE)&&(event.button.y>=0)&&(event.button.y<=hauteur*TAILLE_SPRITE))
						{
							// emplacement de terrain libre
							if (get_terrain(event.button.x/TAILLE_SPRITE, event.button.y/TAILLE_SPRITE,sj.jeu.terrain)==0)
							{
								actionsouris(&sj.jeu,'3', int(event.button.x/TAILLE_SPRITE),  int(event.button.y/TAILLE_SPRITE));
								ajout=0;
								positiontour3.x=(longueur+1)*TAILLE_SPRITE;
								positiontour3.y=6*TAILLE_SPRITE;
							}
							// emplacement de terrain non libre
							else
							{
								ajout=0;
								positiontour3.x=(longueur+1)*TAILLE_SPRITE;
								positiontour3.y=6*TAILLE_SPRITE;
							}
						}
						// clic hors du terrain
						else
						{
							ajout=0;
							positiontour3.x=(longueur+1)*TAILLE_SPRITE;
							positiontour3.y=6*TAILLE_SPRITE;
						}
					}
					// pas de tour en bout de souris et clic sur achat tour3
					else if ((ajout==0)&&(event.button.x>=(longueur+1)*TAILLE_SPRITE)&&(event.button.x<=(longueur+2)*TAILLE_SPRITE)&&(event.button.y<=7*TAILLE_SPRITE)&&(event.button.y>=6*TAILLE_SPRITE))
					{
						ajout=3;
					}
					if (ajout==4)
					{
						// tour4 en bout de souris et clic sur le terrain
						if ((event.button.x>=0)&&(event.button.x<=longueur*TAILLE_SPRITE)&&(event.button.y>=0)&&(event.button.y<=hauteur*TAILLE_SPRITE))
						{
							// emplacement de terrain libre
							if (get_terrain(event.button.x/TAILLE_SPRITE, event.button.y/TAILLE_SPRITE,sj.jeu.terrain)==0)
							{
								actionsouris(&sj.jeu,'4', int(event.button.x/TAILLE_SPRITE),  int(event.button.y/TAILLE_SPRITE));
								ajout=0;
								positiontour4.x=(longueur+5)*TAILLE_SPRITE;
								positiontour4.y=6*TAILLE_SPRITE;
							}
							// emplacement de terrain non libre
							else
							{
								ajout=0;
								positiontour4.x=(longueur+5)*TAILLE_SPRITE;
								positiontour4.y=6*TAILLE_SPRITE;
							}
						}
						// clic hors du terrain
						else
						{
							ajout=0;
							positiontour4.x=(longueur+5)*TAILLE_SPRITE;
							positiontour4.y=6*TAILLE_SPRITE;
						}
					}
					// pas de tour en bout de souris et clic sur achat tour4
					else if ((ajout==0)&&(event.button.x>=(longueur+5)*TAILLE_SPRITE)&&(event.button.x<=(longueur+6)*TAILLE_SPRITE)&&(event.button.y<=8*TAILLE_SPRITE)&&(event.button.y>=6*TAILLE_SPRITE))
					{
						ajout=4;
					}
				}
				else if (((*sj.jeu.menu).etat_menu)==1)
				{
					// cas de la suppression à mettre en place !
				}
				// si on est en fin de partie et qu'on clique sur "REJOUER" :
				else if ((((*sj.jeu.menu).etat_menu)==2)&&(event.button.x>=(((get_longueur(sj.jeu.terrain))+10)/3)*TAILLE_SPRITE)&&(event.button.x<=((((get_longueur(sj.jeu.terrain))+10)/3)+6)*TAILLE_SPRITE)&&(event.button.y<=7*TAILLE_SPRITE)&&(event.button.y>=5*TAILLE_SPRITE))
				{
					// il faut réinitialiser le jeu
					init_jeu(&sj.jeu);
				}
				break;
				// si on déplace la souris :
				case SDL_MOUSEMOTION:
				// on n'a que 4 cas : soit on a la tour1 en bout de souris, soit la tour2, soit la tour3, soit la tour4, dans chacun de ces cas, on fait en sorte que l'image suive le bout de la souris
					if (ajout==1)
					{
						positiontour1.x=(event.motion.x-(0.5*TAILLE_SPRITE));
						positiontour1.y=(event.motion.y-(0.5*TAILLE_SPRITE));
					}
					if (ajout==2)
					{
						positiontour2.x=(event.motion.x-(0.5*TAILLE_SPRITE));
						positiontour2.y=(event.motion.y-(0.5*TAILLE_SPRITE));
					}
					if (ajout==3)
					{
						positiontour3.x=(event.motion.x-(0.5*TAILLE_SPRITE));
						positiontour3.y=(event.motion.y-(0.5*TAILLE_SPRITE));
					}
					if (ajout==4)
					{
						positiontour4.x=(event.motion.x-(0.5*TAILLE_SPRITE));
						positiontour4.y=(event.motion.y-(0.5*TAILLE_SPRITE));
					}
					break;
				default: break;
			}
			// si c'est la fin de la partie (soit on a perdu, soit on a gagné)
			// il faut mettre l'état du menu à jour :
			if (fin_partie(&sj.jeu)==1)
			{
				(*sj.jeu.menu).etat_menu=2;
			}
		}		
		// on affiche le jeu sur le buffer caché
		sdljeuAff (sj);
		// et si on est dans le cas classique, on affiche les tours
		if ((*sj.jeu.menu).etat_menu==0)
		{
			SDL_BlitSurface(nvelle_tour1, NULL, sj.ecran, &positiontour1);
			SDL_BlitSurface(nvelle_tour2, NULL, sj.ecran, &positiontour2);
			SDL_BlitSurface(nvelle_tour3, NULL, sj.ecran, &positiontour3);
			SDL_BlitSurface(nvelle_tour4, NULL, sj.ecran, &positiontour4);
		}
		// on permute les deux buffers (cette fonction ne doit se faire qu'une seule fois dans a boucle)
		SDL_Flip (sj.ecran);
		// on met un petit temps d'attente afin de ne pas surcharger le processeur pour rien...
		SDL_Delay(100);
	}
}

/* Procédure qui va permettre de liberer tous les pointeurs et d'éviter ainsi les
 * fuites de mémoires. Elle ne sera executée qu'une fois juste avant de quitter 
 * le programme (de la meme facon que l'initialisation).
 * Elle prend en paramatre l'adresse d'une structure SDL. */
void sdljeuDetruit (Ssdljeu& sj)
{
	// libération de toutes les surfaces utilisées :
	SDL_FreeSurface (sj.bebete);
	SDL_FreeSurface (sj.chemin);
	SDL_FreeSurface (sj.libre);
	SDL_FreeSurface (sj.tour1);
	SDL_FreeSurface (sj.tour2);
	SDL_FreeSurface (sj.tour3);
	SDL_FreeSurface (sj.tour4);
	SDL_FreeSurface (sj.titre);
	SDL_FreeSurface (sj.portee1);
	SDL_FreeSurface (sj.vitesse1);
	SDL_FreeSurface (sj.puissance1);
	SDL_FreeSurface (sj.prix1);
	SDL_FreeSurface (sj.portee2);
	SDL_FreeSurface (sj.vitesse2);
	SDL_FreeSurface (sj.puissance2);
	SDL_FreeSurface (sj.prix2);
	SDL_FreeSurface (sj.portee3);
	SDL_FreeSurface (sj.vitesse3);
	SDL_FreeSurface (sj.puissance3);
	SDL_FreeSurface (sj.prix3);
	SDL_FreeSurface (sj.portee4);
	SDL_FreeSurface (sj.vitesse4);
	SDL_FreeSurface (sj.puissance4);
	SDL_FreeSurface (sj.prix4);
	SDL_FreeSurface (sj.boutton_start);
	// puis quitter la gestion de police et d'affichage graphique :
	TTF_Quit();
	SDL_Quit();
	
}



SDL_Surface *SDL_load_image(const char* filename )
{
	//Temporary storage for the image that's loaded
	SDL_Surface* loadedImage = NULL;

	//The optimized image that will be used
	SDL_Surface* optimizedImage = NULL;

	//Load the image
	loadedImage = SDL_LoadBMP (filename);

	//If nothing went wrong in loading the image
	if (loadedImage != NULL)
	{
		//Create an optimized image
		optimizedImage = SDL_DisplayFormat (loadedImage);

		//Free the old image
		SDL_FreeSurface (loadedImage);
	}

	//Return the optimized image
	return optimizedImage;
}


void SDL_apply_surface (SDL_Surface* source, SDL_Surface* destination, int x, int y)
{
	//Make a temporary rectangle to hold the offsets
	SDL_Rect offset;

	//Give the offsets to the rectangle
	offset.x = x;
	offset.y = y;

	//Blit the surface
	SDL_BlitSurface (source, NULL, destination, &offset);
}

